package com.ironone.streaming.mediaplayer;

import java.util.Timer;
import java.util.TimerTask;
import com.ironone.streaming.application.FormObject;
import android.media.AudioManager;
import android.media.MediaPlayer;

public class MyMediaPlayer {
	private static MediaPlayer mediaPlayer = null;

	private static int iVolume;
	private final static int INT_VOLUME_MAX = 100;
	private final static int INT_VOLUME_MIN = 0;
	private final static float FLOAT_VOLUME_MAX = 1;
	private final static float FLOAT_VOLUME_MIN = 0;
	private final static int FADE_DURATION = 500; // In milliseconds. Can't be 0

	private static MediaPlayerStatus mediaPlayerStatus = MediaPlayerStatus.RELEASED;
	private static boolean isPlayerOnBackground = false;
	private static boolean isHdOn = true;
	private static boolean isPauseBtnClicked = true;

	public static String SVC_NOTIFICATION = "com.ironone.SERVICE_CALLBACK";   //Activity sending notifications to service
	public static String ACT_NOTIFICATION = "com.ironone.ACTIVITY_CALLBACK";  //Service sending notifications to activity
	public static String VALUE = "value";

	private MyMediaPlayer(){
	}

	public static MediaPlayer getMediaPlayerInstance(){
		if (mediaPlayer == null) {
			mediaPlayer = new MediaPlayer();
		}
		return mediaPlayer;
	}

	public static MediaPlayerStatus getMediaPlayerStatus(){
		return mediaPlayerStatus;
	}

	public static void setMediaPlayerStatus(MediaPlayerStatus status){
		mediaPlayerStatus = status;
	}

	public static boolean isPlaying(){
		try {
			if(mediaPlayer == null) return false;
			return mediaPlayer.isPlaying();
		} catch (Exception e) {
			return false;
		}
	}

	public static boolean getIsPlayerOnBackground(){
		return isPlayerOnBackground;
	}

	public static void setIsPlayerOnBackground(boolean x){
		isPlayerOnBackground = x;
	}

	public static boolean getIsHDOn(){
		return isHdOn;
	}

	public static void setIsHDOn(boolean y){
		isHdOn = y;
	}

	public static boolean getMediaPlayerPauseClicked() {
		return isPauseBtnClicked;
	}

	public static void setMediaPlayerPauseClicked(boolean pStatus) {
		isPauseBtnClicked = pStatus;
	}


	public static void prepareMediaPlayer() throws Exception{
		try {
			getMediaPlayerInstance();
			mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
			
			if(getIsHDOn())
				mediaPlayer.setDataSource(FormObject.getInstance().getHDStream());
			else
				mediaPlayer.setDataSource(FormObject.getInstance().getSDStream());  //FormObject.getInstance().getSDStream()

			if(!MyMediaPlayer.getMediaPlayerPauseClicked()){   //TODO: check this
				mediaPlayerStatus = MediaPlayerStatus.PREPARING;
				mediaPlayer.prepareAsync();
			}
		} catch (Exception e) {
			throw e;
		}
	}

	public static void playMediaPlayer(){
		try {
			if (!isPauseBtnClicked) {
				incVolume(FADE_DURATION);
				mediaPlayer.start();
				mediaPlayerStatus = MediaPlayerStatus.PLAYING;
			}		

			/*try {
				wifiLock.acquire();
			} catch (Exception e) {
				e.printStackTrace();
			}*/

		} catch (Exception e) {
			releaseMediaPlayer();			
		}
	}

	public static void pauseMediaPlayer(){
		try {
			decVolumeAndProceed(FADE_DURATION, MediaPlayerStatus.PAUSED);
		} catch (Exception e) {
			// TODO Auto-generated catch block
		}

		//mediaPlayerStatus = MediaPlayerStatus.paused;

		/*try {
			wifiLock.release();
		} catch (Exception e) {
			e.printStackTrace();
		}*/
	}

	public static void resetMediaPlayer(){
		try {
			if (mediaPlayer != null)
				decVolumeAndProceed(FADE_DURATION, MediaPlayerStatus.RESETED);

			/*try {
				wifiLock.release();
			} catch (Exception e) {
				e.printStackTrace();
			}*/
		} catch (Exception e) {
			// TODO Auto-generated catch block
		}
	}

	public static void releaseMediaPlayer(){
		try {
			if (mediaPlayer != null) {
				decVolumeAndProceed(FADE_DURATION, MediaPlayerStatus.RESETED);

				/*try {
					wifiLock.release();
				} catch (Exception e) {
					e.printStackTrace();
				}*/
			}
		} catch (Exception e) {
			// TODO Auto-generated catch block
		}
	}

	public static void resetAndPrepareMediaPlayer() throws Exception{
		try {
			decVolumeAndProceed(FADE_DURATION, MediaPlayerStatus.RESET_N_PREPARE);

			/*try {
				wifiLock.release();
			} catch (Exception e) {
				e.printStackTrace();
			}*/
		} catch (Exception e) {
			throw e;
		}
	}


	//Start increasing volume in increments
	private static void incVolume(int fadeDuration){
		try {
			if(fadeDuration == 0)
				fadeDuration = 1;

			//Set current volume, depending on fade or not
			if (fadeDuration > 0) 
				iVolume = INT_VOLUME_MIN;
			else 
				iVolume = INT_VOLUME_MAX;

			updateVolume(0);

			//Start increasing volume in increments
			if(fadeDuration > 0)
			{
				final Timer timer = new Timer(true);
				TimerTask timerTask = new TimerTask() 
				{
					@Override
					public void run() 
					{
						updateVolume(1);
						if (iVolume == INT_VOLUME_MAX)
						{
							timer.cancel();
							timer.purge();
						}
					}
				};

				// calculate delay, cannot be zero, set to 1 if zero
				int delay = fadeDuration/INT_VOLUME_MAX;
				if (delay == 0) delay = 1;
				timer.schedule(timerTask, delay, delay);
			}
		} catch (Exception e) {
			// TODO Auto-generated catch block
		}
	}

	static boolean result = false;
	private static void decVolumeAndProceed(int fadeDuration, final MediaPlayerStatus playerStatus) throws Exception{
		try {
			if(fadeDuration == 0)
				fadeDuration = 1;

			//Set current volume, depending on fade or not
			if (fadeDuration > 0)
				iVolume = INT_VOLUME_MAX;
			else
				iVolume = INT_VOLUME_MIN;

			updateVolume(0);

			//Start increasing volume in increments
			if(fadeDuration > 0) {
				final Timer timer = new Timer(true);
				TimerTask timerTask = new TimerTask() {
					@Override
					public void run() {   
						updateVolume(-1);
						if (iVolume == INT_VOLUME_MIN) {
							switch (playerStatus.ordinal()) {
							case 0: //MediaPlayerStatus.playing
								break;

							case 1: //MediaPlayerStatus.paused
								if (mediaPlayer.isPlaying()){ 
									mediaPlayer.pause();
									mediaPlayerStatus = MediaPlayerStatus.PAUSED;
								}
								break;

							case 2: //MediaPlayerStatus.buffering
								break;

							case 3: //MediaPlayerStatus.released
								if(mediaPlayer.isPlaying()) {
									mediaPlayer.stop();				
								}
								mediaPlayer.release();
								mediaPlayer = null;
								mediaPlayerStatus = MediaPlayerStatus.RELEASED;

								break;

							case 4: //MediaPlayerStatus.reseted
								if(mediaPlayer.isPlaying()) {
									mediaPlayer.stop();				
								}
								mediaPlayer.reset();
								mediaPlayerStatus = MediaPlayerStatus.RESETED;
								break;

							case 5: //MediaPlayerStatus.forcePaused
								break;

							case 6: //MediaPlayerStatus.resetAndPrepare  RESET_N_PREPARE
								if(mediaPlayer.isPlaying()) {
									mediaPlayer.stop();
								}
								mediaPlayer.reset();
								mediaPlayerStatus = MediaPlayerStatus.RESETED;
								
								try {
									prepareMediaPlayer();
								} catch (Exception e) {
									result = true;
								}								
								break;

							default:
								break;
							}

							timer.cancel();
							timer.purge();
						}
					}
				};

				// calculate delay, cannot be zero, set to 1 if zero
				int delay = fadeDuration/INT_VOLUME_MAX;
				if (delay == 0) delay = 1;
				timer.schedule(timerTask, delay, delay);
			}						
		} catch (Exception e) {
			throw e;
		}
	}

	private static void updateVolume(int change){
		try {
			//increment or decrement depending on type of fade
			iVolume = iVolume + change;

			//ensure iVolume within boundaries
			if (iVolume < INT_VOLUME_MIN)
				iVolume = INT_VOLUME_MIN;
			else if (iVolume > INT_VOLUME_MAX)
				iVolume = INT_VOLUME_MAX;

			//convert to float value
			float fVolume = 1 - ((float) Math.log(INT_VOLUME_MAX - iVolume) / (float) Math.log(INT_VOLUME_MAX));

			//ensure fVolume within boundaries
			if (fVolume < FLOAT_VOLUME_MIN)
				fVolume = FLOAT_VOLUME_MIN;
			else if (fVolume > FLOAT_VOLUME_MAX)
				fVolume = FLOAT_VOLUME_MAX;     

			mediaPlayer.setVolume(fVolume, fVolume);
		} catch (Exception e) {
			// TODO Auto-generated catch block
		}
	}

}